﻿using System;
using System.Net;
using System.Collections.Generic;
using System.Text;

namespace VodafoneContracts
{
    public abstract class Connection
    {
        public string url;
        public StringBuilder later_url;
        public CookieContainer CookieContainer;
        public Action<HttpWebResponse> prevProcessor;
        public Action<HttpWebResponse> currProcessor;
        public Action onError;

        public abstract void connectHTML (string url, CookieContainer cookie, Action<HttpWebResponse> callnback, Action onError);

        public static void connectHTMLwithGet(string url, CookieContainer cookie, Action<HttpWebResponse> callnback, Action onError)
        {
            var req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.CookieContainer = cookie;
            req.Method = "GET";
            req.BeginGetResponse(
            (IAsyncResult result) =>
            {
                try
                {
                    var request = (HttpWebRequest)result.AsyncState;
                    if (callnback != null)
                        callnback((HttpWebResponse)request.EndGetResponse(result));

                }
                catch (Exception ex)
                {
                    ex.ToString();
                    if (onError != null)
                        onError();
                }
            }, req);
        }


        public static void connectHTMLwithPost(string url, string postData, CookieContainer cookie, Action<HttpWebResponse> callnback, Action onError)
        {
            var req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.CookieContainer = cookie;

            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            //req.ContentLength = data.Length;
            req.BeginGetRequestStream(
                new AsyncCallback(
                    (asynchronousResult) =>
                    {
                        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

                        // End the operation
                        var postStream = request.EndGetRequestStream(asynchronousResult);

                        byte[] data = Encoding.UTF8.GetBytes(postData);
                        // Write to the request stream.
                        postStream.Write(data, 0, data.Length);
                        postStream.Close();

                        // Start the asynchronous operation to get the response
                        req.BeginGetResponse(
                        (IAsyncResult result) =>
                        {
                            try
                            {
                                var _request = (HttpWebRequest)result.AsyncState;
                                if (callnback != null)
                                    callnback((HttpWebResponse)_request.EndGetResponse(result));

                            }
                            catch (Exception ex)
                            {
                                ex.ToString();
                                if (onError != null)
                                    onError();
                            }
                        }, req);

                    }),
                    req);
        }
    }

    public class ConnectionGET : Connection
    {
        public override void connectHTML(string url, CookieContainer cookie, Action<HttpWebResponse> callnback, Action onError)
        {
            connectHTMLwithGet(url, cookie, callnback, onError);               
        }
    }

    public class ConnectionPOST : Connection
    {
        public override void connectHTML(string url, CookieContainer cookie, Action<HttpWebResponse> callnback, Action onError)
        {
            var str = url.Split('?');
            connectHTMLwithPost(str[0], str.Length>1?str[1]:"", cookie, callnback, onError);               
        }
    }
    
    public class ConnectionQueue
    {
        public List<Connection> connections = new List<Connection>();
        public int currentConnection = 0;
        //private bool serving = false;
        private HttpWebResponse lastResponse = null;
        private int trys = 0;
        public static int MAXTRY = 2;
        //System.Windows.Threading.DispatcherTimer timer;
        bool stopped = false;
        public void AddConnection(Connection c)
        {
            connections.Add(c);
        }

        public void Run(int i)
        {
            currentConnection = i;
            Run();
        }
        public void Run()
        {
            stopped = false;
            RunCycle();
        }

        private void RunCycle()
        {
            //if (timer != null)
            //    timer.Stop();
            //timer = new System.Windows.Threading.DispatcherTimer();
            //timer.Interval = TimeSpan.FromMilliseconds(100);
            //timer.Tick += new EventHandler(
            if(stopped || currentConnection >= connections.Count)
                return;
            var nextConn = connections[currentConnection];
            if (nextConn.prevProcessor != null)
                nextConn.prevProcessor(lastResponse);
            if (nextConn.later_url != null)
                nextConn.url = nextConn.later_url.ToString();
            connections[currentConnection].connectHTML(nextConn.url, nextConn.CookieContainer,
                (response) =>
                {
                    if (stopped)
                        return;
                    trys = 1;
                    currentConnection++;
                    nextConn.currProcessor(response);
                    RunCycle();
                },
                () =>
                {
                    trys++;
                    if (trys > MAXTRY)
                    {
                        //timer.Stop();
                        nextConn.onError();
                        return;
                    }
                    RunCycle();
                });
        }

        public void Stop()
        {
            //if (timer != null)
            //    timer.Stop();
            //timer = null;
            stopped = true;
        }
    }
}
